I have searched a lot for this but couldn't find a solution. Here's a similar question with a possible solution in java.
Is there a similar solution in Python?
I have searched a lot for this but couldn't find a solution. Here's a similar question with a possible solution in java.
Is there a similar solution in Python?
Other than Selenium, this example also requires the PIL Imaging library. Sometimes this is put in as one of the standard libraries and sometimes it's not, but if you don't have it you can install it with pip install Pillow
from selenium import webdriver
from PIL import Image
from io import BytesIO
fox = webdriver.Firefox()
fox.get('http://stackoverflow.com/')
# now that we have the preliminary stuff out of the way time to get that image :D
element = fox.find_element_by_id('hlogo') # find part of the page you want image of
location = element.location
size = element.size
png = fox.get_screenshot_as_png() # saves screenshot of entire page
fox.quit()
im = Image.open(BytesIO(png)) # uses PIL library to open image in memory
left = location['x']
top = location['y']
right = location['x'] + size['width']
bottom = location['y'] + size['height']
im = im.crop((left, top, right, bottom)) # defines crop points
im.save('screenshot.png') # saves new cropped image
and finally the output is... the Stackoverflow logo!!!
Now of course this would be overkill for just grabbing a static image but if your want to grab something that requires Javascript to get to this could be a viable solution.
img = fox.get_screenshot_as_png()
and then img = Image.open(StringIO(img))
to load it as PIL image. –
Astrogation im.save('screenshot.png')
is not saving. –
Bartz BytesIO
rather than StringIO
. –
Jarl pixel_ratio = fox.execute_script("return window.devicePixelRatio")
new_size = old_size * pixel_ratio
–
Wisp driver.get_window_size()
2. Subtract the height of the address bar from the height of the browser window 3. Now resize the screenshot to the new height and width from set 1 and 2 –
Polyhymnia right = location['x'] + old_size['width']* pixel_ratio bottom = location['y'] + old_size['height']* pixel_ratio
–
Revivalist im.save
is not saving but it is also not throwing error, should I ask a new question for this? When I type im.show()
a transparent image window of required size is appearing –
Nucleonics AttributeError: type object 'ElementObject' has no attribute 'location'
–
Zygote Worked for me in python3.5
from selenium import webdriver
fox = webdriver.Firefox()
fox.get('http://stackoverflow.com/')
image = fox.find_element_by_id('hlogo').screenshot_as_png
p.s.
To save to file
image=driver.find_element_by_id('hlogo').screenshot(output_file_path)
image = driver.find_element_by_id('el_id').screenshot_as_png
is this an attribute of the element, and how can i save this as an image? –
Herrod image = driver.find_element_by_id('el_id').screenshot(output_file_path)
. Please refer here for API doc. –
Incommunicado im = Image.open(BytesIO(image)) # uses PIL library to open image in memory im.save('example.png')
–
Laevo screenshot_as_base64
attribute –
Pigtail I wrote this useful python3 function.
from base64 import b64decode
from wand.image import Image
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.common.action_chains import ActionChains
import math
def get_element_screenshot(element: WebElement) -> bytes:
driver = element._parent
ActionChains(driver).move_to_element(element).perform() # focus
src_base64 = driver.get_screenshot_as_base64()
scr_png = b64decode(src_base64)
scr_img = Image(blob=scr_png)
x = element.location["x"]
y = element.location["y"]
w = element.size["width"]
h = element.size["height"]
scr_img.crop(
left=math.floor(x),
top=math.floor(y),
width=math.ceil(w),
height=math.ceil(h),
)
return scr_img.make_blob()
It returns png image of displayed element as bytes.
Limitation: element must fit in viewport.
You must install wand module to work with it.
x = element.location_once_scrolled_into_view["x"] y = element.location_once_scrolled_into_view["y"]
since location
may return a y larger than the window. –
Separates Here is a function that does just that, The sizes must be casted to integers before being passed to the crop function :
from PIL import Image
from StringIO import StringIO
def capture_element(element,driver):
location = element.location
size = element.size
img = driver.get_screenshot_as_png()
img = Image.open(StringIO(img))
left = location['x']
top = location['y']
right = location['x'] + size['width']
bottom = location['y'] + size['height']
img = img.crop((int(left), int(top), int(right), int(bottom)))
img.save('screenshot.png')
TypeError: initial_value must be str or None, not bytes
–
Vow Expanding on the comments in response to RandomPhobia's very nice answer, here are two solutions with correct import statements that will open a full-screen screenshot without first saving to a file:
from selenium import webdriver
from PIL import Image
from StringIO import StringIO
import base64
DRIVER = 'chromedriver'
browser = webdriver.Chrome(DRIVER)
browser.get( "http:\\\\www.bbc.co.uk" )
img 1 = Image.open(StringIO(base64.decodestring(browser.get_screenshot_as_base64())))
img 2 = Image.open(StringIO(browser.get_screenshot_as_png()))
And because I'm sure your next question is, "Well that's great but which one is fastest?", here's how to determine it (I find the first method to be the fastest by some distance):
import timeit
setup = '''
from selenium import webdriver
from PIL import Image
from StringIO import StringIO
import base64
DRIVER = 'chromedriver'
browser = webdriver.Chrome(DRIVER)
browser.get( "http:\\\\www.bbc.co.uk" )
file_name = 'tmp.png'
'''
print timeit.Timer('Image.open(StringIO(browser.get_screenshot_as_png()))', setup=setup).repeat(2, 10)
print timeit.Timer('Image.open(StringIO(base64.decodestring(browser.get_screenshot_as_base64())))', setup=setup).repeat(2, 10)
print timeit.Timer('browser.get_screenshot_as_file(file_name); pil_img = Image.open(file_name)', setup=setup).repeat(2, 10)
Screenshot by Element:
from PIL import Image
from io import BytesIO
image = self.browser.driver.find_element_by_class_name('example.bla.bla').screenshot_as_png
im = Image.open(BytesIO(image)) # uses PIL library to open image in memory
im.save('example.png')
WebDriverException: Message: unknown error: failed to parse value of getElementRegion (Session info: chrome=78.0.3904.108)
–
Braxy Just simple as that:
element = driver.find_element_by_class_name('myclass')
element.screenshot('screenshot.png')
I converted @randomphobia's answer into a function. I also used @bummis' suggestion of using location_once_scrolled_into_view
instead of location
in order to generalize no matter the size of the page.
from selenium import webdriver
from PIL import Image
from io import BytesIO
def take_screenshot(element, driver, filename='screenshot.png'):
location = element.location_once_scrolled_into_view
size = element.size
png = driver.get_screenshot_as_png() # saves screenshot of entire page
im = Image.open(BytesIO(png)) # uses PIL library to open image in memory
left = location['x']
top = location['y']
right = location['x'] + size['width']
bottom = location['y'] + size['height']
im = im.crop((left, top, right, bottom)) # defines crop points
im.save(filename) # saves new cropped image
Here's a gist: https://gist.github.com/WittmannF/b714d3ceb7b6a5cd50002f11fb5a4929
© 2022 - 2024 — McMap. All rights reserved.
img = Image.open(StringIO(base64.decodestring(driver.get_screenshot_as_base64())))
– Yahrzeit